#include "scheduling_window.h"
#include "ui_scheduling_window.h"

#include <sys/time.h>

Scheduling_Window::Scheduling_Window(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Scheduling_Window)
{
    ui->setupUi(this);


    QStringList list ;
    list<<"抢占式优先级调度"<<"非抢占式优先级调度"<<"时间片调度";
    this->ui->comboBox_modeSelection->addItems(list);

    //this->ui->pushButton_automaticOperation->setCheckable(true);

    this->ui->spinBox_lengthOfReady->setValue(10);
    this->ui->spinBox_TimeLength->setValue(5);

    //内存初始化(0-31为操作系统占用内存,32-199可供其他进程使用)
    for(int i = 0;i<=31;i++){
        memory[i] = 1;
    }
    for(int i = 32;i<=199;i++){
        memory[i] = 0;
    }
    //1 被占用
    //0 未被占用

    QPushButton *button = new QPushButton("系统占用内存\nSIZE: 32",this);
    int i = 31/200.0*750;
    button->setGeometry(1590,65,242,i);
    button->setStyleSheet("background-color:#1C1C1C;color:#F8F8FF");
    QAction *act = new QAction();
    QFont boldFont = act ->font();
    boldFont.setBold(true);//字体加粗
    button->setFont(boldFont);

    freeMemory = new QPushButton("空闲内存\nSIZE: 168",this);
    freeMemory->setGeometry(1590,179,242,168/200.0*750);
    freeMemory->setStyleSheet("background-color:rgb(193,255,193);color:rgb(0,206,209)");
    freeMemory->setFont(boldFont);

    //初始化向量
    inMemroyPCB *p = new inMemroyPCB(nullptr,32,168);
    p->btn = freeMemory;
    inMemoryPCBLine.push_back(*p);



    //设置不可改变状态
    this->ui->listView_processInReadyLine->setEditTriggers(QAbstractItemView::NoEditTriggers);
    this->ui->listView_processInWaitingLine->setEditTriggers(QAbstractItemView::NoEditTriggers);

    //更新列表
    connect(this,SIGNAL(updateLine(int,QListView*)),this,SLOT(updateLineSlot(int,QListView*)));

    //清空信息栏
    connect(this,SIGNAL(clearEditLine()),this,SLOT(clearEditLineSlot()));

    //选中点击事件
    connect(this->ui->listView_processInWaitingLine,SIGNAL(clicked(QModelIndex)),this,SLOT(updateIOSlot(QModelIndex)));


    //鼠标指针选中显示needTime
    //connect(this->ui->listView_processInReadyLine,SIGNAL(hoverEnabled(QModelIndex)),this,SLOT(showNeedTimeSlot(QModelIndex)));


}

Scheduling_Window::~Scheduling_Window()
{
    delete ui;
}

//点击更新按钮 1)若项目PID不存在,则创建该项目
//           2)若IP存在,则更新不为空的状态栏
void Scheduling_Window::on_pushButton_updateProcess_clicked()
{
  //  qDebug()<<"从头输出";
 //   coutVector();
    QString PID = this->ui->lineEdit_PID->text();
    //若PID一栏为空
    if(this->ui->lineEdit_PID->text() == NULL){
        QMessageBox::information(NULL,"Information","请输入PID!");
        return;
    }
    //若存在PID 更新状态
 //   qDebug()<<"if 下面输出";
 //   coutVector();
    if(searchSamePID(PID,readyLine)||searchSamePID(PID,waitingLine)||searchSamePID(PID,hangupLine)||searchSamePID(PID,completedLine))
    {

    }
    //否则创建新项目
    else{
      //  qDebug()<<"在else里输出";
     //   coutVector();
        PCB* p;
//        if(this->ui->lineEdit_frontPCB->text() == NULL){
//             p = createNewProcess(this->ui->lineEdit_PID->text(),this->ui->lineEdit_Name->text(),this->ui->lineEdit_needTime->text().toInt(),this->ui->lineEdit_priorityWeight->text().toInt(),this->ui->lineEdit_needMemorySIze->text().toInt());
//        }
//        else {
//             p = createNewProcess(this->ui->lineEdit_PID->text(),this->ui->lineEdit_Name->text(),this->ui->lineEdit_needTime->text().toInt(),this->ui->lineEdit_priorityWeight->text().toInt(),this->ui->lineEdit_needMemorySIze->text().toInt(),this->ui->lineEdit_frontPCB->text());

//        }
        p = createNewProcess(this->ui->lineEdit_PID->text(),this->ui->lineEdit_Name->text(),this->ui->lineEdit_needTime->text().toInt(),this->ui->lineEdit_priorityWeight->text().toInt(),this->ui->lineEdit_needMemorySIze->text().toInt(),this->ui->lineEdit_frontPCB->text(),this->ui->lineEdit_backPCB->text());
        //若道数已被占满则放入后备队列
        if(readyLine.size()+1>this->ui->spinBox_lengthOfReady->value())
        {
            reserveLine.push_back(*p);

            emit updateLine(3,this->ui->listView_reserveLine);
            return;
        }
      //  qDebug()<<"在判断前检查";
       // coutMemory();
        //若道数不满则进行内存判断,若存在可用空间,则将其放入ready队列,否则放入后备队列
        if(!memoryJudge(*p)){
            reserveLine.push_back(*p);
            emit updateLine(3,this->ui->listView_reserveLine);
            emit clearEditLine();
            return;
        }
        readyLine.push_back(*p);
        sortByPriorityWeight(readyLine);



        emit updateLine(1,this->ui->listView_processInReadyLine);
        emit clearEditLine();


     //   qDebug()<<"在加入成功后检查";
     //   coutVector();

        return;

    }
}

//判断PID是否存在
bool Scheduling_Window::searchSamePID(QString PID, std::vector<PCB> Line)
{
    if(Line.empty())
        return false;
    int size = Line.size();
    for(int i = 0;i <= size-1;i++)
    {
        if(Line.at(i).PID==PID)
        {
            return true;
        }
    }
    return false;
}

//创建新项目
PCB* Scheduling_Window::createNewProcess(QString PID, QString name, int needTime, int priorityWeight,int needMemorySize)
{
    PCB* p = new PCB(name,PID,NULL,NULL,needTime,priorityWeight,1,needMemorySize);
    return p;
}

PCB* Scheduling_Window::createNewProcess(QString PID, QString name, int needTime, int priorityWeight,int needMemorySize,QString frontID){
  //  qDebug()<<frontID;
    PCB* p = new PCB(name,PID,NULL,NULL,needTime,priorityWeight,1,needMemorySize,frontID);
    return p;
}

PCB* Scheduling_Window::createNewProcess(QString PID, QString name, int needTime, int priorityWeight,int needMemorySize,QString frontID,QString backID){
    PCB* p = new PCB(name,PID,NULL,NULL,needTime,priorityWeight,1,needMemorySize,frontID,backID);
    return p;
}

//更新列表
void Scheduling_Window::updateLineSlot(int i,QListView * q)
{

    switch (i) {

    case 1:{
        int size = readyLine.size();

        int nowMode = this->ui->comboBox_modeSelection->currentIndex();
        if(nowMode == 1|| nowMode == 0)
          sortByPriorityWeight(readyLine);

        QStringList list;
        for(int j = 0;j <= size-1;j++)
        {
           // QString s = readyLine.at(j).PID+"   "+readyLine.at(j).processName+"   "+QString::number(readyLine.at(j).priorityWeight);
            QString s ="进程名: "+ readyLine.at(j).processName+'\n'+"PID: "+readyLine.at(j).PID+"       优先权:"+QString::number(readyLine.at(j).priorityWeight);
            list<<s;
        }
        QStringListModel *model = new QStringListModel(list);

        q->setModel(model);
        break;
    }
    case 2:{
        int size = waitingLine.size();
        QStringList list;
        for(int j = 0;j <= size-1;j++)
        {
            //QString s = waitingLine.at(j).PID+"   "+waitingLine.at(j).processName+"   "+QString::number(waitingLine.at(j).priorityWeight);
            QString s = waitingLine.at(j).processName+'\n'+waitingLine.at(j).PID+"       "+QString::number(waitingLine.at(j).priorityWeight)+"       "+QString::number(waitingLine.at(j).needTime);
            list<<s;
        }
        QStringListModel *model = new QStringListModel(list);
        q->setModel(model);
        break;
    }
    case 3:{
        int size = reserveLine.size();
        QStringList list;
        for(int j = 0;j <= size-1;j++)
        {
            QString s = reserveLine.at(j).processName+'\n'+reserveLine.at(j).PID+"       "+QString::number(reserveLine.at(j).priorityWeight)+"       "+QString::number(reserveLine.at(j).needTime);
            list<<s;
        }
        QStringListModel *model = new QStringListModel(list);
        q->setModel(model);
        break;
    }
    case 0:{
        int size = completedLine.size();
        QStringList list;
        for(int j = 0;j <= size-1;j++)
        {
            QString s = completedLine.at(j).PID+"       "+completedLine.at(j).processName;
            list<<s;
        }
        QStringListModel *model = new QStringListModel(list);
        q->setModel(model);
        break;
    }
    case -1:{
        int size = hangupLine.size();
        QStringList list;
        for(int j = 0;j <= size-1;j++)
        {
            //QString s = hangupLine.at(j).PID+"   "+hangupLine.at(j).processName+"   "+QString::number(hangupLine.at(j).priorityWeight);
            QString s = hangupLine.at(j).processName+'\n'+hangupLine.at(j).PID+"       "+QString::number(hangupLine.at(j).priorityWeight)+"       "+QString::number(hangupLine.at(j).needTime);
            list<<s;
        }
        QStringListModel *model = new QStringListModel(list);
        q->setModel(model);
        break;
    }
    }
}

//清空编辑列表
void Scheduling_Window::clearEditLineSlot()
{
    this->ui->lineEdit_PID->clear();
    this->ui->lineEdit_Name->clear();
    this->ui->lineEdit_Input->clear();
    this->ui->textBrowser_outPut->clear();
    this->ui->lineEdit_needTime->clear();
    this->ui->lineEdit_priorityWeight->clear();
}

//依据优先级为readyLine排序
void Scheduling_Window::sortByPriorityWeight(std::vector<PCB> &readyLine)
{
    if(readyLine.size()==0||readyLine.size()==1)
        return;
    for(int i = 0 ; i<= readyLine.size()-2;i++)
    {
        for(int j = 0;j<=readyLine.size()-2;j++)
        {

            if(readyLine.at(j).priorityWeight<readyLine.at(j+1).priorityWeight)
            {
                swap(readyLine.at(j).PID,readyLine.at(j+1).PID);
                swap(readyLine.at(j).inPut,readyLine.at(j+1).inPut);
                swap(readyLine.at(j).outPut,readyLine.at(j+1).outPut);
                swap(readyLine.at(j).needTime,readyLine.at(j+1).needTime);
                swap(readyLine.at(j).processName,readyLine.at(j+1).processName);
                swap(readyLine.at(j).priorityWeight,readyLine.at(j+1).priorityWeight);
                swap(readyLine.at(j).frontID,readyLine.at(j+1).frontID);
                swap(readyLine.at(j).backID,readyLine.at(j+1).backID);
            }
        }
    }
}

//交换字符串
void Scheduling_Window::swap(QString &s1, QString &s2)
{
    QString s3;
    s3 = s1;
    s1 = s2;
    s2 = s3;
}

//交换int类型变量
void Scheduling_Window::swap(int &s1, int &s2)
{
    int s3;
    s3 = s1;
    s1 = s2;
    s2 = s3;
}

//判断内存空间是否够用
bool Scheduling_Window::memoryJudge(PCB &p)
{
    int MaxLength = 0;
    int needSize = p.needMemorySize;
    int beginPosition = 32;
    //寻找是否存在一个合适区间
    for(int i = 32;i <= MEMORYSIZE-1; i++){
        if(memory[i] == 0){
            MaxLength++;
            if(MaxLength>=needSize)
            {
                p.memoryStartAddress = beginPosition;
                for(int j = beginPosition;j<=beginPosition+needSize-1;j++)
                {
                    memory[j] = 1;
                }
                inMemroyPCB *inMP = new inMemroyPCB(&p,beginPosition,needSize);
                updateMemoryLine(inMP);
                return true;
            }
        }
        else {
            MaxLength = 0;
            beginPosition = i+1;
        }
    }
    return false;
}

void Scheduling_Window::updateMemoryLine(inMemroyPCB *p)
{
    int i;
    //寻找到需要被切分的空闲内存空间
    qDebug()<<inMemoryPCBLine.size();
    for(i = 0;i<= inMemoryPCBLine.size()-1;i++){
        if(inMemoryPCBLine.at(i).memoryBeginPoistion==p->memoryBeginPoistion)
            break;
    }
    //切分
    inMemoryPCBLine.insert(inMemoryPCBLine.begin()+i,*p);
    inMemoryPCBLine.at(i+1).length -=p->length;
    inMemoryPCBLine.at(i+1).memoryBeginPoistion += p->length;
    delete inMemoryPCBLine.at(i+1).btn;
    //inMemoryPCBLine.at(i+1).btn->setParent(nullptr);
    //更新显示面板
   // qDebug()<<"那到这里了吗???"<<endl;
    updateMemoryShow(&inMemoryPCBLine.at(i));
    updateMemoryShow(&inMemoryPCBLine.at(i+1));


    if(inMemoryPCBLine.at(i+1).length==0){
        inMemoryPCBLine.erase(inMemoryPCBLine.begin()+i+1);
    }

 //   qDebug()<<"在updateMemoryLine处检查";
 //   coutVector();
}

//更新内存显示
void Scheduling_Window::updateMemoryShow(inMemroyPCB* inMP){
    //若为空闲内存的更新
    if(inMP->p==nullptr){
        //qDebug()<<"空闲内存BeginPosition:"<<inMP->memoryBeginPoistion<<"Length:"<<inMP->length;
      //  qDebug()<<inMP->length<<"  "<<inMP->memoryBeginPoistion;
        QString str = QString::number(inMP->length);
        inMP->btn = new QPushButton("空闲内存\nSIZE: "+str,this);
        inMP->btn->setGeometry(OX,OY+(inMP->memoryBeginPoistion-3)/MEMORYSIZE*ALLHEIGHT,XLength,inMP->length/MEMORYSIZE*ALLHEIGHT);
        inMP->btn->setStyleSheet("background-color:rgb(193,255,193);color:rgb(0,206,209)");
        QAction *act = new QAction();
        QFont boldFont = act ->font();
        boldFont.setBold(true);//字体加粗
        inMP->btn->setFont(boldFont);
        inMP->btn->show();
     //   qDebug()<<"找不出bug怎么办";
    }
    else{
        QString str = inMP->p->processName+"\nSIZE: "+QString::number(inMP->length);
        inMP->btn = new QPushButton(str,this);
        inMP->btn->setGeometry(OX,OY+(inMP->memoryBeginPoistion-2)/MEMORYSIZE*ALLHEIGHT,XLength,inMP->length/MEMORYSIZE*ALLHEIGHT);
        inMP->btn->setStyleSheet("background-color:rgb(255,99,71);color:rgb(255,215,0)");
        QAction *act = new QAction();
        QFont boldFont = act ->font();
        boldFont.setBold(true);//字体加粗
        inMP->btn->setFont(boldFont);
        inMP->btn->show();
    }
  //  qDebug()<<"在updateMemoryShow处更新";
  //  coutVector();
}

//为未占用内存生成对应的button
void Scheduling_Window::updateNotUseMemory(int beginPosition, int length)
{
    inMemroyPCB *p = new inMemroyPCB(nullptr,beginPosition,length);
    //浏览该向量,找到
}

//进程完成后 更新vector
void Scheduling_Window::updateCompletedProcess(PCB *p)
{
    qDebug()<<"在进程结束后检查";
    coutVector();
//    qDebug()<<"size is "<<inMemoryPCBLine.size();
    int i;
    qDebug()<<p->PID;
    for(i = 0;i<=inMemoryPCBLine.size()-1;i++){
        if(inMemoryPCBLine.at(i).p!=nullptr){
            qDebug()<<i<<" 的PID "<<inMemoryPCBLine.at(i).p->PID;
        }
        else{
            qDebug()<<i<<" 为空闲内存";
        }
    }
    for( i = 0;i<=inMemoryPCBLine.size()-1;i++){
 //       qDebug()<<"第"<<i<<"次循环";
        if(inMemoryPCBLine.at(i).p!=nullptr){
            if(inMemoryPCBLine.at(i).p->PID==p->PID)
                break;
        }
    }
  //  qDebug()<<"size is "<<inMemoryPCBLine.size();
//    if(inMemoryPCBLine.size()-1<i)
//        i--;
    //先更新memory中数据
    int beginPosition = inMemoryPCBLine.at(i).memoryBeginPoistion;
    int length = inMemoryPCBLine.at(i).length;
    for(int j = beginPosition;j<=beginPosition+length-1;j++){
        memory[j]=0;
    }

//    qDebug()<<"在第几个位置呢???"<<i;
//    qDebug()<<"一共有多大呢???"<<inMemoryPCBLine.size();
    //先判断前一个向量是否需要改变
    //如果不需要
    if(i==0||inMemoryPCBLine.at(i-1).p!=nullptr){
        //再判断后一个向量是否需要改变
        //如果不需要
        if(i==inMemoryPCBLine.size()-1||inMemoryPCBLine.at(i+1).p!=nullptr){
            //只改变i位置
            qDebug()<<"内存前后不需要改变位置";
            delete inMemoryPCBLine.at(i).btn;
            inMemoryPCBLine.at(i).p=nullptr;
            updateMemoryShow(&inMemoryPCBLine.at(i));
        }
        //如果需要
        else {
            qDebug()<<"内存后方有空闲内存";
           // qDebug()<<"now i is "<<i;
            //合并i位置与i+1位置到i
            inMemoryPCBLine.at(i).length += inMemoryPCBLine.at(i+1).length;
            //删除i+1位置的button
           // inMemoryPCBLine.at(i+1).btn->setParent(nullptr);
            qDebug()<<inMemoryPCBLine.at(i+1).btn->text();
//            inMemoryPCBLine.at(i).btn->hide();
//            inMemoryPCBLine.at(i+1).btn->hide();
            delete  inMemoryPCBLine.at(i).btn;
            delete  inMemoryPCBLine.at(i+1).btn;

            //移除i+1位置
            inMemoryPCBLine.erase(inMemoryPCBLine.begin()+i+1);
            //更新
            inMemoryPCBLine.at(i).p=nullptr;
            updateMemoryShow(&inMemoryPCBLine.at(i));
        }
    }
    //如果需要
    else {
        //再判断后一个向量是否需要改变
        //如果不需要
        if(i==inMemoryPCBLine.size()-1||inMemoryPCBLine.at(i+1).p!=nullptr){
            qDebug()<<"内存前方有空闲内存";
            //合并i-1位置与i到位置i-1
            inMemoryPCBLine.at(i-1).length += inMemoryPCBLine.at(i).length;
            //删除botton
            delete  inMemoryPCBLine.at(i-1).btn;
            delete  inMemoryPCBLine.at(i).btn;
            //移除i位置
            inMemoryPCBLine.erase(inMemoryPCBLine.begin()+i);
            //更新
            updateMemoryShow(&inMemoryPCBLine.at(i-1));
        }
        //如果需要
        else {
            qDebug()<<"内存前方和后方有空闲内存";
            //合并i-1位置与i,i+1到位置i-1
            inMemoryPCBLine.at(i-1).length += (inMemoryPCBLine.at(i).length+inMemoryPCBLine.at(i+1).length);
            //删除botton
            delete  inMemoryPCBLine.at(i-1).btn;
            delete  inMemoryPCBLine.at(i).btn;
            delete  inMemoryPCBLine.at(i+1).btn;
            //移除i,i+1位置
            inMemoryPCBLine.erase(inMemoryPCBLine.begin()+i);
            inMemoryPCBLine.erase(inMemoryPCBLine.begin()+i);
            //更新
            updateMemoryShow(&inMemoryPCBLine.at(i-1));

         //   coutVector();
        }
    }
    for(i = 0;i<=inMemoryPCBLine.size()-1;i++){
        if(inMemoryPCBLine.at(i).p!=nullptr){
            qDebug()<<i<<" 的PID "<<inMemoryPCBLine.at(i).p->PID;
        }
        else{
            qDebug()<<i<<" 为空闲内存";
        }
    }

}

//输出向量内容
void Scheduling_Window::coutVector()
{
    qDebug()<<"++++++++++++++++++++++++++++++++++++++++++++++++++";
    for(int i = 0;i<=inMemoryPCBLine.size()-1;i++){
        //qDebug()<<"输出"<<i;
        if(inMemoryPCBLine.at(i).p==nullptr){
            qDebug()<<"第"<<i<<"个位置为空闲内存,beginPosition: "<<inMemoryPCBLine.at(i).memoryBeginPoistion<<",length: "<<inMemoryPCBLine.at(i).length;
        }
        else {
//            qDebug()<<"到这里了吗?";
//            qDebug()<<inMemoryPCBLine.at(i).p->PID;
            qDebug()<<"第"<<i<<"个位置为进程"<<inMemoryPCBLine.at(i).p->processName<<",beginPosition: "<<inMemoryPCBLine.at(i).memoryBeginPoistion<<",length: "<<inMemoryPCBLine.at(i).length;
        }
    }
    qDebug()<<"++++++++++++++++++++++++++++++++++++++++++++++++++";
}

//cout内存数据
void Scheduling_Window::coutMemory()
{
    qDebug()<<"**************************************************";
    int judge = memory[0];
    int beginPosition = 0;
    int length = 0;
    int i;
    for( i = 0;i<=199;i++){
        if(judge!=memory[i]){
            qDebug()<<beginPosition<<"位置为"<<judge<<"长度"<<length;
            beginPosition = i;
            length = 1;
            judge = memory[i];
        }
        else {
            length++;
        }
    }
    qDebug()<<beginPosition<<"位置为"<<judge<<"长度"<<length;
    qDebug()<<"**************************************************";
}

//清空正在运行进程信息
void Scheduling_Window::clearRunningInformation()
{
    this->ui->label_processName->clear();
    this->ui->label_PID->clear();
    this->ui->label_needTime->clear();
    this->ui->label_priorityWeight->clear();
}

//运行1时间单位
void Scheduling_Window::on_pushButton_goOneTIme_clicked()
{
    //qDebug()<<"进行了点击!";
    int currentMode = this->ui->comboBox_modeSelection->currentIndex();
   // qDebug()<<"点击运行后检查";
 //   coutVector();
//    0 为 抢占式优先级调度
//    1 为 非抢占式优先级调度
//    2 为 时间片调度
    switch (currentMode) {
    case 0:{

        //若队列不为空,首先将队列中所有等待项目olderTime+1,若有olderTime为10的项目,则其优先级+1
        if(!readyLine.empty()){
            for(int i = 0;i <= readyLine.size()-1;i++){
                readyLine.at(i).olderTime++;
                if(readyLine.at(i).olderTime%10==0){
              //      readyLine.at(i).priorityWeight++;
                }
            }
        }

        //若有正在运行的项目,且其要进行I/O操作,则其直接进入waiting队列等待I/O
        if(running&&running->mode==0){
            waitingLine.push_back(runningProcess);
            emit updateLine(2,this->ui->listView_processInWaitingLine);
            running = NULL;
        }

        //若队列为空且有正在运行的项目,则根据剩余时间进行判断
        if(readyLine.empty()&&running){
            if(running->needTime==0){
                //更新completedlist数据
                PCB completedProcess(*running);
                completedLine.push_back(completedProcess);
                emit updateLine(0,this->ui->listView_processCompleted);
            //    qDebug()<<"在完成前一刻检查";
            //    coutVector();
                qDebug()<<"RUNNING IS "<<running->processName;
                updateCompletedProcess(running);


                running = NULL;
                clearRunningInformation();
                QMessageBox::information(NULL,"Information","您已完成所有项目!");
                return;
            }
            else{
           //     qDebug()<<"在运行中检查";
            //    coutVector();
                //更改显示面板数据
                running->needTime--;
                this->ui->label_PID->setText(running->PID+"");
                this->ui->label_processName->setText(running->processName);
                this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                this->ui->label_needTime->setText(QString::number(running->needTime));

                //IO判断
                IOJudge(runningProcess);

                return;
            }
        }

        //若无正在运行的项目,则取队首项目放入运行
        if(!running&&!readyLine.empty()){
           // runningProcess(readyLine.at(0));
            //取队首项目

       //     int head = 0;
            //判断其有无前驱进程
            for(int head = 0;head<=readyLine.size()-1;head++){

                if(readyLine.at(head).frontID!=NULL){
                    qDebug()<<"asdasd";
                    bool is = false;
                    for(int i = head+1;i<=readyLine.size()-1;i++){
                        qDebug()<<readyLine.at(head).frontID<<"   "<<readyLine.at(i).PID;
                        if(readyLine.at(head).frontID==readyLine.at(i).PID){

                            is = true;
                        }
                    }
                    if(!is){
                        qDebug()<<"ssssss";
                        runningProcess.copyPCB(runningProcess,readyLine.at(head));
                        running = &runningProcess;
                        readyLine.erase(readyLine.begin());
                        //后备队列进入ready队列
                        loadProc();

                  //      qDebug()<<"在运行中检查";
                 //       coutVector();
                        //更改显示面板数据
                        running->needTime--;
                        this->ui->label_PID->setText(running->PID+"");
                        this->ui->label_processName->setText(running->processName);
                        this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                        this->ui->label_needTime->setText(QString::number(running->needTime));

                        //IO判断
                        IOJudge(runningProcess);


                        //更新readyList
                        emit updateLine(1,this->ui->listView_processInReadyLine);
                        return;

                    }
                }
                else {
                    runningProcess.copyPCB(runningProcess,readyLine.at(head));
                    running = &runningProcess;
                    readyLine.erase(readyLine.begin()+head);

                    //后备队列进入ready队列
                    loadProc();

              //      qDebug()<<"在运行中检查";
             //       coutVector();
                    //更改显示面板数据
                    running->needTime--;
                    this->ui->label_PID->setText(running->PID+"");
                    this->ui->label_processName->setText(running->processName);
                    this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                    this->ui->label_needTime->setText(QString::number(running->needTime));

                    //IO判断
                    IOJudge(runningProcess);


                    //更新readyList
                    emit updateLine(1,this->ui->listView_processInReadyLine);
                    return;
                }
            }







        }
        //若有未完成的运行项目且该项目优先权高
        if(running&&running->needTime!=0&&running->priorityWeight>=readyLine.at(0).priorityWeight&&!readyLine.empty()){
            //更改显示面板数据
            running->needTime--;
            this->ui->label_PID->setText(running->PID+"");
            this->ui->label_processName->setText(running->processName);
            this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
            this->ui->label_needTime->setText(QString::number(running->needTime));

            //IO判断
            IOJudge(runningProcess);

            return;
        }
        //若有未完成的运行项目且该项目needTime为0
        if(running&&running->needTime==0){
            //更新completedlist数据
            PCB completedProcess(*running);
            completedLine.push_back(completedProcess);
            emit updateLine(0,this->ui->listView_processCompleted);
            qDebug()<<"RUNNING IS "<<running->processName;
            updateCompletedProcess(running);
            //如果有后继项目
            if(running->backID!=NULL){
                for(int i = 0;i<=readyLine.size()-1;i++){
                    if(readyLine.at(i).PID==running->backID){
                        runningProcess.copyPCB(runningProcess,readyLine.at(i));
                        running = &runningProcess;
                        readyLine.erase(readyLine.begin()+i);

                        //后备队列进入ready队列
                        loadProc();

                        //更改显示面板数据
                        running->needTime--;
                        this->ui->label_PID->setText(running->PID+"");
                        this->ui->label_processName->setText(running->processName);
                        this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                        this->ui->label_needTime->setText(QString::number(running->needTime));

                        //IO判断
                        IOJudge(runningProcess);

                        //更新readyList
                        emit updateLine(1,this->ui->listView_processInReadyLine);
                        return;
                    }
                }
            }

            //若队列不为空则放入新项目
            if(!readyLine.empty()){
                qDebug()<<3;
                runningProcess.copyPCB(runningProcess,readyLine.at(0));
                running = &runningProcess;
                readyLine.erase(readyLine.begin());

                //后备队列进入ready队列
                loadProc();

                //更改显示面板数据
                running->needTime--;
                this->ui->label_PID->setText(running->PID+"");
                this->ui->label_processName->setText(running->processName);
                this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                this->ui->label_needTime->setText(QString::number(running->needTime));

                //IO判断
                IOJudge(runningProcess);

                //更新readyList
                emit updateLine(1,this->ui->listView_processInReadyLine);
                return;
            }
            //队列为空则结束运行
            else {
                running = NULL;
                clearRunningInformation();
                QMessageBox::information(NULL,"Information","您已完成所有项目!");
                return;
            }

        }
        //若有未完成的项目 但运行项目优先级低
        if(running&&running->needTime!=0&&running->needTime<readyLine.at(0).priorityWeight&&!readyLine.empty()){

            //先保存低优先级信息
            PCB lowProcess(*running);
            lowProcess.copyPCB(lowProcess,runningProcess);
            readyLine.push_back(lowProcess);

            //再保存高优先级信息
            runningProcess.copyPCB(runningProcess,readyLine.at(0));

            //调整ready队列
            readyLine.erase(readyLine.begin());
            sortByPriorityWeight(readyLine);
            emit updateLine(1,this->ui->listView_processInReadyLine);

            //更新指针
            running = &runningProcess;

            //更改显示面板数据
            running->needTime--;
            this->ui->label_PID->setText(running->PID+"");
            this->ui->label_processName->setText(running->processName);
            this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
            this->ui->label_needTime->setText(QString::number(running->needTime));

            //IO判断
            IOJudge(runningProcess);

            return;
        }
    }
    case 1:{

        //若队列不为空,首先将队列中所有等待项目olderTime+1,若有olderTime为10的项目,则其优先级+1
        if(!readyLine.empty()){
            for(int i = 0;i <= readyLine.size()-1;i++){
                readyLine.at(i).olderTime++;
                if(readyLine.at(i).olderTime%10==0){
                    readyLine.at(i).priorityWeight++;
                }
            }
        }

        //若有正在运行的项目,且其要进行I/O操作,则其直接进入waiting队列等待I/O
        if(running&&running->mode==0){
            waitingLine.push_back(runningProcess);
            emit updateLine(2,this->ui->listView_processInWaitingLine);
            running = NULL;
        }

        //若队列为空且有正在运行的项目,则根据剩余时间进行判断
        if(readyLine.empty()&&running){
            if(running->needTime==0){

                //更新completedlist数据
                PCB completedProcess(*running);
                completedLine.push_back(completedProcess);
                emit updateLine(0,this->ui->listView_processCompleted);
                updateCompletedProcess(running);

                running = NULL;
                QMessageBox::information(NULL,"Information","您已完成所有项目!");
                return;
            }
            else{
                //更改显示面板数据
                running->needTime--;
                this->ui->label_PID->setText(running->PID+"");
                this->ui->label_processName->setText(running->processName);
                this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                this->ui->label_needTime->setText(QString::number(running->needTime));

                //IO判断
                IOJudge(runningProcess);

                return;
            }
        }

        //若无正在运行的项目,则取队首项目放入运行
        if(!running&&!readyLine.empty()){
           // runningProcess(readyLine.at(0));
            //取队首项目
            runningProcess.copyPCB(runningProcess,readyLine.at(0));
            running = &runningProcess;
            readyLine.erase(readyLine.begin());

            //后备队列进入ready队列
            loadProc();

            //更改显示面板数据
            running->needTime--;
            this->ui->label_PID->setText(running->PID+"");
            this->ui->label_processName->setText(running->processName);
            this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
            this->ui->label_needTime->setText(QString::number(running->needTime));

            //IO判断
            IOJudge(runningProcess);

            //更新readyList
            emit updateLine(1,this->ui->listView_processInReadyLine);
            return;
        }
        //若有未完成的运行项目
        if(running&&running->needTime!=0&&!readyLine.empty()){
            //更改显示面板数据
            running->needTime--;
            this->ui->label_PID->setText(running->PID+"");
            this->ui->label_processName->setText(running->processName);
            this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
            this->ui->label_needTime->setText(QString::number(running->needTime));

            //IO判断
            IOJudge(runningProcess);

            return;
        }
        //若有未完成的运行项目且该项目needTime为0
        if(running&&running->needTime==0){
            //更新completedlist数据
            PCB completedProcess(*running);
            completedLine.push_back(completedProcess);
            emit updateLine(0,this->ui->listView_processCompleted);
            updateCompletedProcess(running);

            //若队列不为空则放入新项目
            if(!readyLine.empty()){
                qDebug()<<3;
                runningProcess.copyPCB(runningProcess,readyLine.at(0));
                running = &runningProcess;
                readyLine.erase(readyLine.begin());

                //后备队列进入ready队列
                loadProc();

                //更改显示面板数据
                running->needTime--;
                this->ui->label_PID->setText(running->PID+"");
                this->ui->label_processName->setText(running->processName);
                this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                this->ui->label_needTime->setText(QString::number(running->needTime));

                //IO判断
                IOJudge(runningProcess);

                //更新readyList
                emit updateLine(1,this->ui->listView_processInReadyLine);
                return;
            }
            //队列为空则结束运行
            else {

                running = NULL;
                QMessageBox::information(NULL,"Information","您已完成所有项目!");
                return;
            }

        }

    }
    case 2:{
        //无进程运行时先从队列中选取一个进程运行
        if(!running&&!readyLine.empty()){
            //取队首项目
            runningProcess.copyPCB(runningProcess,readyLine.at(0));
            running = &runningProcess;
            readyLine.erase(readyLine.begin());

            //后备队列进入ready队列
            loadProc();

            //更改显示面板数据
            running->needTime--;
            this->ui->label_PID->setText(running->PID+"");
            this->ui->label_processName->setText(running->processName);
            this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
            this->ui->label_needTime->setText(QString::number(running->needTime));

            //时间计数器+1
            timeLength++;

            //更新readyList
            emit updateLine(1,this->ui->listView_processInReadyLine);
            return;
        }

        //若有正在运行的项目,且其要进行I/O操作,则其直接进入waiting队列等待I/O
        if(running&&running->mode==0){
            waitingLine.push_back(runningProcess);
            emit updateLine(2,this->ui->listView_processInWaitingLine);
            running = NULL;
        }

        //若有进程运行但needTime为0
        if(running&&running->needTime==0){

            //更新completedlist数据
            PCB completedProcess(*running);
            completedLine.push_back(completedProcess);
            emit updateLine(0,this->ui->listView_processCompleted);
            updateCompletedProcess(running);

            //时间计数器归零
            timeLength = 0;

            //若队列不为空则放入新进程
            if(!readyLine.empty()){
                //取队首项目
                runningProcess.copyPCB(runningProcess,readyLine.at(0));
                running = &runningProcess;
                readyLine.erase(readyLine.begin());

                //后备队列进入ready队列
                loadProc();

                //更改显示面板数据
                running->needTime--;
                this->ui->label_PID->setText(running->PID+"");
                this->ui->label_processName->setText(running->processName);
                this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                this->ui->label_needTime->setText(QString::number(running->needTime));

                //IO判断
                IOJudge(runningProcess);

                //时间计数器+1
                timeLength++;

                //更新readyList
                emit updateLine(1,this->ui->listView_processInReadyLine);
                return;
            }
            //队列为空
            else{
                running = NULL;
                QMessageBox::information(NULL,"Information","您已完成所有项目!");
                return;
            }
        }

        //若有进程运行且needTime不为0
        if(running&&running->needTime>0){

            //若已超时则将该项目放入ready队尾
            if(timeLength == this->ui->spinBox_TimeLength->value()){
                //计时器归零
                timeLength = 0;

                //先保存未完成项目信息
                PCB unCompletedProcess(*running);
                unCompletedProcess.copyPCB(unCompletedProcess,runningProcess);
                readyLine.push_back(unCompletedProcess);

                //保存队首进程
                runningProcess.copyPCB(runningProcess,readyLine.at(0));

                //更新ready队列
                readyLine.erase(readyLine.begin());
                emit updateLine(1,this->ui->listView_processInReadyLine);

                //计时器+1
                timeLength++;

                //更新指针
                running = &runningProcess;

                //更改显示面板数据
                running->needTime--;
                this->ui->label_PID->setText(running->PID+"");
                this->ui->label_processName->setText(running->processName);
                this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                this->ui->label_needTime->setText(QString::number(running->needTime));

                //IO判断
                IOJudge(runningProcess);

                return;


            }

            //若未超时则继续运行
            else {
                //计时器++
                timeLength++;

                //更改显示面板数据
                running->needTime--;
                this->ui->label_PID->setText(running->PID+"");
                this->ui->label_processName->setText(running->processName);
                this->ui->label_priorityWeight->setText(QString::number(running->priorityWeight));
                this->ui->label_needTime->setText(QString::number(running->needTime));

                //IO判断
                IOJudge(runningProcess);

                return;
            }
        }

        //若无进程运行且队列为空
        if(!running&&readyLine.empty()){
            QMessageBox::information(NULL,"Information","请加入新进程!");
        }
    }
    }
}

//自动运行
void Scheduling_Window::on_pushButton_automaticOperation_toggled(bool checked)
{
    continuedJudge++;
    while (true) {
       // Sleep(1000)
        //gettimeofday();
        this->ui->pushButton_goOneTIme->click();
    }
}

//挂起或解除挂起
void Scheduling_Window::on_pushButton_addOneProcess_clicked()
{
    //挂起操作
    if(!readyLine.empty()){
        QModelIndexList modelIndexListReadyList = this->ui->listView_processInReadyLine->selectionModel()->selectedIndexes();
        for(int i = 0;i <=modelIndexListReadyList.size()-1;i++){
            //获取行数
            int rowNum = modelIndexListReadyList.at(i).row();
            qDebug()<<rowNum;

            //挂起
            hangupLine.push_back(readyLine.at(rowNum));
            readyLine.erase(readyLine.begin()+rowNum);

            //后备队列进入ready队列
            loadProc();

            //更新列表
            emit updateLine(1,this->ui->listView_processInReadyLine);
            emit updateLine(-1,this->ui->listView_processHangUp);
        }
    }

    if(!waitingLine.empty()){
        QModelIndexList modelIndexListWaitingList = this->ui->listView_processInWaitingLine->selectionModel()->selectedIndexes();
        for(int j = 0;j <= modelIndexListWaitingList.size()-1;j++){
            //获取行数
            int rowNum = modelIndexListWaitingList.at(j).row();

            //挂起
            hangupLine.push_back(waitingLine.at(rowNum));
            waitingLine.erase(waitingLine.begin()+rowNum);


            //更新列表
            emit updateLine(2,this->ui->listView_processInWaitingLine);
            emit updateLine(-1,this->ui->listView_processHangUp);
        }
    }

    //解除挂起
    if(!hangupLine.empty()){
        QModelIndexList modelIndexListHangupList = this->ui->listView_processHangUp->selectionModel()->selectedIndexes();
        for(int k = 0;k <= modelIndexListHangupList.size()-1;k++){
            //获取行数
            int rowNum = modelIndexListHangupList.at(k).row();

            //解除挂起分配回对应队列
            if(hangupLine.at(rowNum).mode==1){

                //若内存不足则放入后备队列
                if(!memoryJudge(hangupLine.at(rowNum))){
                    reserveLine.push_back(hangupLine.at(rowNum));
                    hangupLine.erase(hangupLine.begin()+rowNum);
                    emit updateLine(3,this->ui->listView_reserveLine);
                    emit updateLine(-1,this->ui->listView_processHangUp);
                    return;
                }

                //若道数已被占满则放入后备队列
                if(readyLine.size()+1>this->ui->spinBox_lengthOfReady->value())
                {
                    reserveLine.push_back(hangupLine.at(rowNum));
                    hangupLine.erase(hangupLine.begin()+rowNum);

                    emit updateLine(3,this->ui->listView_reserveLine);
                    emit updateLine(-1,this->ui->listView_processHangUp);
                    return;
                }

                readyLine.push_back(hangupLine.at(rowNum));
                hangupLine.erase(hangupLine.begin()+rowNum);

                //更新对应列表
                emit updateLine(1,this->ui->listView_processInReadyLine);
                emit updateLine(-1,this->ui->listView_processHangUp);

                return;
            }

            if(hangupLine.at(rowNum).mode==0){
                waitingLine.push_back(hangupLine.at(rowNum));
                hangupLine.erase(hangupLine.begin()+rowNum);

                //更新对应列表
                emit updateLine(0,this->ui->listView_processInWaitingLine);
                emit updateLine(-1,this->ui->listView_processHangUp);

                return;
            }
        }
    }
}

//随机触发IO事件
void Scheduling_Window::IOJudge(PCB &p)
{
    int k = rand()%100;
    if(k<this->ui->spinBox_IO->value())
    {
        MyResources newResources;
        p.mode = 0;
        p.outPut = newResources.OProblems[rand()%5];
    }
}

//点击后显示该项目对应信息
void Scheduling_Window::updateIOSlot(QModelIndex index)
{
    this->ui->lineEdit_PID->setText(waitingLine.at(index.row()).PID);
    this->ui->lineEdit_Name->setText(waitingLine.at(index.row()).processName);
    this->ui->lineEdit_needTime->setText(QString::number(waitingLine.at(index.row()).needTime));
    this->ui->lineEdit_priorityWeight->setText(QString::number(waitingLine.at(index.row()).priorityWeight));
    this->ui->textBrowser_outPut->setText(waitingLine.at(index.row()).outPut);

    //此时将编辑信息列表状态设为不可改变
    this->ui->lineEdit_PID->setEnabled(false);
    this->ui->lineEdit_Name->setEnabled(false);
    this->ui->lineEdit_needTime->setEnabled(false);
    this->ui->lineEdit_priorityWeight->setEnabled(false);

    //将该进程放入正在编辑PCB中
    editingProcess.copyPCB(editingProcess,waitingLine.at(index.row()));
    editing = &waitingLine.at(index.row());

    //记录选中行数
    nowSelectedRow = index.row();
}

//输入button
void Scheduling_Window::on_pushButton_input_clicked()
{
    if(!editing){
        QMessageBox::information(NULL,"Information","请选择待输入进程!");
        return;
    }

    if(this->ui->lineEdit_Input == NULL){
        QMessageBox::information(NULL,"Information","请完成输入!");
    }
    else{
        editingProcess.mode = 1;
        editingProcess.inPut = this->ui->lineEdit_Input->text();

        //若道数已被占满则放入后备队列
        if(readyLine.size()+1>this->ui->spinBox_lengthOfReady->value())
        {
            reserveLine.push_back(editingProcess);

            emit updateLine(3,this->ui->listView_reserveLine);

            waitingLine.erase(waitingLine.begin()+nowSelectedRow);

            //重置状态
            editing = NULL;
            nowSelectedRow = -1;

            //清空编辑列表并解封对应编辑栏
            emit clearEditLine();
            this->ui->lineEdit_PID->setEnabled(true);
            this->ui->lineEdit_Name->setEnabled(true);
            this->ui->lineEdit_needTime->setEnabled(true);
            this->ui->lineEdit_priorityWeight->setEnabled(true);

            emit updateLine(2,this->ui->listView_processInWaitingLine);

        }

        //输入完成后重回ready队列
        readyLine.push_back(editingProcess);
        waitingLine.erase(waitingLine.begin()+nowSelectedRow);

        //重置状态
        editing = NULL;
        nowSelectedRow = -1;

        //清空编辑列表并解封对应编辑栏
        emit clearEditLine();
        this->ui->lineEdit_PID->setEnabled(true);
        this->ui->lineEdit_Name->setEnabled(true);
        this->ui->lineEdit_needTime->setEnabled(true);
        this->ui->lineEdit_priorityWeight->setEnabled(true);

        //更新ready和waiting队列
        emit updateLine(1,this->ui->listView_processInReadyLine);
        emit updateLine(2,this->ui->listView_processInWaitingLine);
    }
}

//点击后随机生成一个进程
void Scheduling_Window::on_pushButton_randomAddProcess_clicked()
{

    PCB *randomProcess = new PCB();

    randomProcess->randomPCB(*randomProcess);

    //若道数已被占满则放入后备队列
    if(readyLine.size()+1>this->ui->spinBox_lengthOfReady->value())
    {
        reserveLine.push_back(*randomProcess);

        emit updateLine(3,this->ui->listView_reserveLine);
        return;
    }

    //若道数不满则进行内存判断,若存在可用空间,则将其放入ready队列,否则放入后备队列
    if(!memoryJudge(*randomProcess)){
        reserveLine.push_back(*randomProcess);
        emit updateLine(3,this->ui->listView_reserveLine);
        emit clearEditLine();
        return;
    }
    readyLine.push_back(*randomProcess);

    emit updateLine(1,this->ui->listView_processInReadyLine);
    emit clearEditLine();


 //   qDebug()<<"在加入成功后检查";
  //  coutVector();

    return;


//    //更新ready队列 并更新readyLine
//    readyLine.push_back(randomProcess);
//    emit updateLine(1,this->ui->listView_processInReadyLine);

}

//后备队列进入ready队列
void Scheduling_Window::loadProc()
{
    if(reserveLine.empty())
        return ;
    PCB tempPCB = reserveLine.at(0);
    readyLine.push_back(tempPCB);
    reserveLine.erase(reserveLine.begin());

    emit updateLine(3,this->ui->listView_reserveLine);
}

//若道数已被占满则放入后备队列
void Scheduling_Window::reserveJudge(int rowNum)
{

    if(readyLine.size()+1>this->ui->spinBox_lengthOfReady->value())
    {
        reserveLine.push_back(hangupLine.at(rowNum));
        hangupLine.erase(hangupLine.begin()+rowNum);

        emit updateLine(3,this->ui->listView_reserveLine);
        emit updateLine(-1,this->ui->listView_processHangUp);
        return;
    }
}

//清空向量
void Scheduling_Window::clearVector(std::vector<PCB> &v)
{
    v.erase(v.begin(),v.end());
}

//清空所有列表
void Scheduling_Window::on_pushButton_clearList_clicked()
{
    //清空向量
    clearVector(readyLine);
    clearVector(waitingLine);
    clearVector(hangupLine);
    clearVector(completedLine);
    clearVector(reserveLine);

    //更新列表
    emit updateLine(1,this->ui->listView_processInReadyLine);
    emit updateLine(2,this->ui->listView_processInWaitingLine);
    emit updateLine(3,this->ui->listView_reserveLine);
    emit updateLine(0,this->ui->listView_processCompleted);
    emit updateLine(-1,this->ui->listView_processHangUp);

    //重置指针
    running = nullptr;
    editing = nullptr;

    nowSelectedRow = -1;

    //清空编辑列表并解封对应编辑栏
    emit clearEditLine();
    this->ui->lineEdit_PID->setEnabled(true);
    this->ui->lineEdit_Name->setEnabled(true);
    this->ui->lineEdit_needTime->setEnabled(true);
    this->ui->lineEdit_priorityWeight->setEnabled(true);

    //清空running界面
    this->ui->label_PID->clear();
    this->ui->label_needTime->clear();
    this->ui->label_processName->clear();
    this->ui->label_priorityWeight->clear();

}

//挂起正在运行的进程
void Scheduling_Window::on_pushButton_hang_clicked()
{
    if(running==nullptr){
        QMessageBox::information(nullptr,"Information","当前无正在运行的进程");
    }else{
        hangupLine.push_back(*running);
        updateCompletedProcess(running);
        running = nullptr;
        emit updateLine(-1,this->ui->listView_processHangUp);
        clearRunningInformation();
    }
}

